// Package object 将字符串切片封装为对象，提供线程安全的操作方法
package object

import ( // 导入依赖的包
	"sort"    // 导入排序相关功能的包
	"strings" // 导入字符串处理相关功能的包
	"sync"    // 导入同步机制相关功能的包（如互斥锁）
)

// stringSliceLocker 接口，包含锁的基本操作方法
type stringSliceLocker interface {
	Lock()    // 加锁操作
	Unlock()  // 解锁操作
	RLock()   // 读锁操作
	RUnlock() // 读解锁操作
}

// stringSliceNotLocker 实现stringSliceLocker接口的方法，但方法为空
type stringSliceNotLocker struct{}

func (stringSliceNotLocker) Lock()    {} // 实现加锁操作，无实际操作
func (stringSliceNotLocker) Unlock()  {} // 实现解锁操作，无实际操作
func (stringSliceNotLocker) RLock()   {} // 实现读锁操作，无实际操作
func (stringSliceNotLocker) RUnlock() {} // 实现读解锁操作，无实际操作

// stringSliceSafeLocker 内嵌sync.RWMutex来保证线程安全
type stringSliceSafeLocker struct {
	locker sync.RWMutex // 声明一个读写互斥锁
}

func (l *stringSliceSafeLocker) Lock()    { l.locker.Lock() }    // 实现加锁操作
func (l *stringSliceSafeLocker) Unlock()  { l.locker.Unlock() }  // 实现解锁操作
func (l *stringSliceSafeLocker) RLock()   { l.locker.RLock() }   // 实现读锁操作
func (l *stringSliceSafeLocker) RUnlock() { l.locker.RUnlock() } // 实现读解锁操作

// StringSlice 结构体，用于存储字符串切片，并通过locker来控制线程安全
type StringSlice struct {
	Values []string          // 存储实际的字符串切片数据
	locker stringSliceLocker // 使用stringSliceLocker接口实现锁定机制
}

// NewStringSlice 函数创建StringSlice实例，可以选择是否线程安全
func NewStringSlice(values []string, threadSafe bool) *StringSlice {
	deduplicatedValues := removeDuplicates(values) // 对初始切片去重
	s := &StringSlice{Values: deduplicatedValues}  // 创建StringSlice实例，设置去重后的数据
	if threadSafe {
		s.locker = &stringSliceSafeLocker{} // 如果需要线程安全，则设置locker为StringSliceSafeLocker
	} else {
		s.locker = stringSliceNotLocker{} // 否则设置为不进行任何操作的locker
	}
	return s // 返回创建的StringSlice实例
}

// Set 方法设置切片的值
func (s *StringSlice) Set(values []string) {
	s.locker.Lock()         // 加锁
	defer s.locker.Unlock() // 方法最后解锁
	s.Values = values       // 设置Values为传入的切片
}

// Get 方法获取切片的值
func (s *StringSlice) Get() []string {
	s.locker.RLock()         // 读锁
	defer s.locker.RUnlock() // 方法最后读解锁
	return s.Values          // 返回Values切片
}

// Remove 方法根据值移除元素
func (s *StringSlice) Remove(value string, allowChangeOrder bool) {
	s.locker.Lock()   // 加锁
	var indices []int // 用于存储需要删除的元素索引
	for i, v := range s.Values {
		if v == value {
			indices = append(indices, i) // 如果找到需要删除的值，将索引添加到indices切片中
		}
	}
	s.locker.Unlock() // 解锁
	if len(indices) > 0 {
		s.RemoveAtIndices(indices, allowChangeOrder) // 如果找到需要删除的元素，根据索引移除
	}
}

// RemoveAtIndex 方法根据索引移除元素
func (s *StringSlice) RemoveAtIndex(index int, allowChangeOrder bool) {
	s.locker.Lock()         // 加锁
	defer s.locker.Unlock() // 方法最后解锁
	if allowChangeOrder {
		s.Values[index] = s.Values[len(s.Values)-1] // 如果允许改变顺序，将最后一个元素移动到待删除元素的位置
		s.Values = s.Values[:len(s.Values)-1]       // 缩减切片大小，移除最后一个元素
	} else {
		s.Values = append(s.Values[:index], s.Values[index+1:]...) // 不允许改变顺序，直接移除元素
	}
}

// RemoveAtIndices 方法根据一组索引移除多个元素
func (s *StringSlice) RemoveAtIndices(indices []int, allowChangeOrder bool) {
	if allowChangeOrder {
		toBeRemoved := make(map[int]bool) // 创建一个map来标记待删除元素
		for _, index := range indices {
			toBeRemoved[index] = true // 标记待删除元素
		}
		s.locker.Lock()           // 加锁
		newValues := s.Values[:0] // 创建新的切片，用于存储未被删除的元素
		for i, value := range s.Values {
			if !toBeRemoved[i] {
				newValues = append(newValues, value) // 如果当前索引不在待删除map中，则将元素添加到新切片中
			}
		}
		s.Values = newValues // 更新Values为没有被删除元素的新切片
		s.locker.Unlock()    // 解锁
	} else {
		sort.Sort(sort.Reverse(sort.IntSlice(indices))) // 如果不允许改变顺序，先对索引进行降序排序
		for _, index := range indices {
			s.RemoveAtIndex(index, false) // 逐个索引移除元素
		}
	}
}

// Clean 方法清空切片
func (s *StringSlice) Clean() {
	s.locker.Lock()         // 加锁
	defer s.locker.Unlock() // 方法最后解锁
	s.Values = nil          // 将Values设置为nil，即清空切片
}

// Contains 方法判断切片中是否包含关键字
func (s *StringSlice) Contains(keyword string) bool {
	s.locker.RLock()         // 读锁
	defer s.locker.RUnlock() // 方法最后读解锁
	for _, v := range s.Values {
		if strings.Contains(v, keyword) {
			return true // 如果找到包含关键字的元素，返回true
		}
	}
	return false // 否则返回false
}

// ExactMatch 方法判断切片中是否有元素与关键字完全匹配
func (s *StringSlice) ExactMatch(keyword string) bool {
	s.locker.RLock()         // 读锁
	defer s.locker.RUnlock() // 方法最后读解锁
	for _, v := range s.Values {
		if v == keyword {
			return true // 如果找到完全匹配的元素，返回true
		}
	}
	return false // 否则返回false
}

// Size 方法返回切片的长度
func (s *StringSlice) Size() int {
	s.locker.RLock()         // 读锁
	defer s.locker.RUnlock() // 方法最后读解锁
	return len(s.Values)     // 返回Values的长度
}

// Add 方法向切片中添加一个元素
func (s *StringSlice) Add(item string) {
	s.locker.Lock()                   // 加锁
	defer s.locker.Unlock()           // 方法最后解锁
	s.Values = append(s.Values, item) // 将元素添加到Values切片的末尾
}

// RemoveIfNotContains 方法移除切片中不包含关键字的元素
func (s *StringSlice) RemoveIfNotContains(keyword string) {
	s.locker.Lock()         // 加锁
	defer s.locker.Unlock() // 方法最后解锁
	i := 0                  // 初始化索引
	for i < len(s.Values) {
		if !strings.Contains(s.Values[i], keyword) {
			// 如果当前元素不包含关键字，替换为最后一个元素，并缩短切片长度
			s.Values[i] = s.Values[len(s.Values)-1]
			s.Values = s.Values[:len(s.Values)-1]
		} else {
			// 如果包含关键字，索引递增
			i++
		}
	}
}

// RemoveIfContains 方法移除切片中包含关键字的元素
func (s *StringSlice) RemoveIfContains(keyword string) {
	s.locker.Lock()         // 加锁
	defer s.locker.Unlock() // 方法最后解锁
	i := 0                  // 初始化索引
	for i < len(s.Values) {
		if strings.Contains(s.Values[i], keyword) {
			// 如果当前元素包含关键字，替换为最后一个元素，并缩短切片长度
			s.Values[i] = s.Values[len(s.Values)-1]
			s.Values = s.Values[:len(s.Values)-1]
		} else {
			// 如果不包含关键字，索引递增
			i++
		}
	}
}

// Search 方法返回包含关键字的所有元素及其索引
func (s *StringSlice) Search(keyword string) map[int]string {
	s.locker.RLock()               // 读锁
	defer s.locker.RUnlock()       // 方法最后读解锁
	result := make(map[int]string) // 创建一个map存储结果
	for i, v := range s.Values {
		if strings.Contains(v, keyword) {
			result[i] = v // 如果元素包含关键字，添加到结果map中
		}
	}
	return result // 返回包含关键字的元素及其索引的map
}

// Clone 方法创建并返回一个当前副本
func (s *StringSlice) Clone(threadSafe bool) *StringSlice {
	s.locker.RLock()                         // 读锁
	defer s.locker.RUnlock()                 // 方法最后读解锁
	clone := make([]string, len(s.Values))   // 创建一个与当前Values相同长度的切片
	copy(clone, s.Values)                    // 复制当前Values的元素到新切片
	return NewStringSlice(clone, threadSafe) // 使用新切片和threadSafe参数创建新的StringSlice实例，并返回
}

// AppendWithoutDuplicates 方法将新元素添加到切片中，同时确保没有重复
func (s *StringSlice) AppendWithoutDuplicates(newItems []string) {
	s.locker.RLock()          // 读锁
	originalValues := s.Get() // 获取当前的Values复本
	s.locker.RUnlock()        // 方法最后读解锁
	// 将原始值和新元素合并后去重
	mergedAndDeduplicated := removeDuplicates(append(originalValues, newItems...))
	s.locker.Lock()                  // 加锁
	defer s.locker.Unlock()          // 方法最后解锁
	s.Values = mergedAndDeduplicated // 设置Values为合并后去重的切片
}

// removeDuplicates 函数用于去除字符串切片中的重复元素
func removeDuplicates(slice []string) []string {
	dedup := make([]string, 0, len(slice)) // 创建一个新切片用于存储去重后的结果
	seen := make(map[string]bool)          // 创建一个map记录已经看到的元素
	for _, val := range slice {
		if !seen[val] {
			seen[val] = true           // 标记元素已看到
			dedup = append(dedup, val) // 将未重复的元素添加到新切片中
		}
	}
	return dedup // 返回去重后的切片
}
